package org.example;

import org.apache.commons.lang.StringUtils;
import org.example.http.HttpDownloader;
import org.example.http.OkHttpDownloader;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Locale;
import java.util.TimerTask;

public class MainFrame {
    private static final String READY_TEXT = "就绪";
    private JTextField txtUrl;
    private JTextField txtFolder;
    private JButton btnBrowse;
    private JButton btnDown;
    private JCheckBox 自动创建目录CheckBox;
    private JPanel panelStatus;
    private JLabel labelStatus;
    JPanel mainPanel;
    JFileChooser chooser = new JFileChooser(); // 创建一个文件对话框

    private boolean downloadStarted;

    public MainFrame() {
        btnDown.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(StringUtils.isEmpty(txtUrl.getText())){
                    messageDialog("请输入下载文件地址");
                    return;
                }
                if(StringUtils.isEmpty(txtFolder.getText())){
                    messageDialog("请输入目标文件/夹路径");
                    return;
                }
                doDownload();
            }
        });
        btnBrowse.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                doBrowse();
            }
        });
        //chooser.setCurrentDirectory(new File("E:/")); // 设置文件对话框的当前目录
        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        FileSystemView fsv = FileSystemView.getFileSystemView(); //注意了，这里重要的一句
        //System.out.println(fsv.getHomeDirectory()); //得到桌面路径
        chooser.setCurrentDirectory(fsv.getHomeDirectory());
        chooser.setDialogTitle("请选择目标的文件/文件夹...");
        chooser.setApproveButtonText("确定");

        chooser.setFileFilter(new FileFilter() { // 设置文件对话框的文件过滤器
            @Override
            public boolean accept(File file) { // 判断当前文件是否满足过滤条件，只有满足条件的才会显示在对话框中
                // 目录满足条件，扩展名为txt的文件也满足条件
                return file.isDirectory() || file.isFile();
            }

            @Override
            public String getDescription() { // 获取过滤器的描述
                return "可选择任何文件或者文件夹";
            }
        });
        txtUrl.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                extractFilename();
            }

            @Override
            public void focusGained(FocusEvent e) {
                txtUrl.selectAll();
            }
        });

        labelStatus.setText(READY_TEXT);
    }

    private void extractFilename() {
        if(StringUtils.isEmpty(txtFolder.getText())){
            txtFolder.setText(getFilename(txtUrl.getText())); //自动填充文件名
        }
    }

    private void doBrowse() {
        // 设置文件对话框的类型，这里的对话框准备打开文件
        chooser.setDialogType(JFileChooser.OPEN_DIALOG);
        // 显示文件打开的对话框
        int result = chooser.showOpenDialog(mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) { // 单击了确定按钮
            // 获取在文件对话框中选择的文件
            File file = chooser.getSelectedFile();
            //label.setText("<html>准备打开的文件路径为：" + file.getAbsolutePath() + "</html>");
            String fullpath = file.getAbsolutePath();
            if(fullpath.toLowerCase().startsWith("c:\\windows")){
                messageDialog("不能将文件保存在windows目录下,请重新选择");
                return;
            }
            txtFolder.setText(fullpath);
        } else { // 未单击确定按钮
            setTextAndDelayClear("取消打开文件");
        }
    }

    private void messageDialog(String message) {
        JOptionPane.showMessageDialog(mainPanel, message, "提示", JOptionPane.INFORMATION_MESSAGE);
    }
    private void errorDialog(String message) {
        JOptionPane.showMessageDialog(mainPanel, message, "出错了", JOptionPane.ERROR_MESSAGE);
    }

    private void setTextAndDelayClear(String msg){
        labelStatus.setText(msg);
        Timer timer=new  Timer(2000,new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                labelStatus.setText(READY_TEXT);
            }
        });

        //启动定时器
        timer.start();

    }
    private void doDownload() {
        String url = txtUrl.getText().trim();
        String fullpath = getFullPath(txtFolder.getText().trim(), url);
        if(new File(fullpath).exists()){ //文件存在
            int option = JOptionPane.showConfirmDialog(mainPanel,"文件存在，是否覆盖", "文件覆盖确认", JOptionPane.YES_NO_CANCEL_OPTION);
            if(option != JOptionPane.YES_OPTION){
                messageDialog("下载取消");
                return; //不覆盖，只能取消
            }
        }

        if(!url.startsWith("http://") && !url.startsWith("https://" )){ //不是url，那就是本地文件
             copyLocalFile(url, fullpath);
             return;
        }
        if (!downloadStarted) {
            btnDown.setEnabled(false);
            downloadStarted = true;
            new Thread() {
                @Override
                public void run() {
//                            String url = "https://dl.360safe.com/drvmgr/360DrvMgrInstaller_net.exe";
                    new OkHttpDownloader(url, fullpath).downloadAsync(new OkHttpDownloader.OkCallback() {
                        @Override
                        public void prepare(Object msg) {
                            labelStatus.setText(msg.toString());
                        }

                        @Override
                        public void onProgress(long progress) {
                            labelStatus.setText("下载中..." + progress + "%");
                        }

                        @Override
                        public void onFinish() {

                            setTextAndDelayClear("下载完成");
                            downloadStarted = false;
                            btnDown.setEnabled(true);
                        }

                        @Override
                        public void onError(IOException ex) {

                            setTextAndDelayClear(ex.getMessage());
                            downloadStarted = false;
                            btnDown.setEnabled(true);
                            errorDialog("下载失败，错误信息看状态栏");
                        }
                    });
                }
            }.run(); //下载是异步的，这里就不用start()启动线程了
        }
    }

    private void copyLocalFile(String srcPath, String destPath) {
        File src = new File(srcPath);
        if(!src.isFile()){
            errorDialog("源文件不存在: " + src.getAbsolutePath());
            return;
        }
        btnDown.setEnabled(false);
        labelStatus.setText("准备复制本地文件");
        try (FileChannel in = new FileInputStream(src).getChannel();
             FileChannel out = new FileOutputStream(new File(destPath)).getChannel()){
            in.transferTo(0, in.size(), out);

            /*
            //缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //将通道中的数据存入缓冲区
            while (in.read(buf) != -1){
                buf.flip();//切换到读模式
                //将缓缓从去的数据写入通道
                out.write(buf);
                buf.clear();//缓冲区重置
            }*/

        } catch (Exception ex) {
            //e.printStackTrace();
            setTextAndDelayClear(ex.getMessage());
            btnDown.setEnabled(true);
            return;
        }
        //labelStatus.setText("本地文件复制完成");
        setTextAndDelayClear("本地文件复制完成");
        btnDown.setEnabled(true);
    }

    private String getFullPath(String folder, String url) {
        if(folder.endsWith("\\") || folder.endsWith("/")){
            return folder + getFilename(url);
        }else{
            if(new File(folder).isDirectory()){
                return folder+"/" + getFilename(url);
            }
            return folder; //这个就是文件路径(还有文件名)
        }
    }

    private String getFilename(String url) {
        int pos = url.lastIndexOf("/");
        if(pos == -1){
            pos = url.lastIndexOf("\\");
        }
        if(pos == -1){
            throw new IllegalArgumentException("Invalid url/path: " + url);
        }
        return url.substring(pos+1);
    }
}
